'''
Created on Dec 30, 2009

@author: DOW2Fan99

Copyright (c) 2009 dow2fan99

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
'''

import os
import logging
import zipfile
import sys

# random notes:
## prompt on error to send log to dow2fan99@gmail.com ? no personal info is transmitted, just log contents, give option to show complete contents to user
## scan for appears-to-be-valid dow2 application path? pirates don't get support
## prompt license at every app run, require agreement to continue, also prompt warnings based on gfwl installation status

# common functions
##<*> find dow2 userdata dir (Documents/My Game/Dawn of War 2/ usually)
##<*> find GFWL userdata dir (Application Settings/Microsoft/XLive/Content/ usually)
##<*> ZIP files (they handle crc within)
##<*> easy detect if file or folder exists

LOG_FILENAME = 'DOW2HelpTool_Log.txt'
MYDOCUMENTS_DOW2_USERDATA_PATH = '\My Documents\My Games\Dawn of War 2\Saved Games'
APPDATA_GFWL_USERDATA_PATH_Win7 = '\AppData\Local\Xlive\Content'
APPDATA_GFWL_USERDATA_PATH_XP = '\Local Settings\Application Data\Microsoft\Xlive\Content'
DEFAULT_BACKUP_ZIP_FILENAME = 'DOW2SaveGamesBackup.zip'

def loggingSetup():
    # set up logging facilities
    logging.basicConfig(level=logging.DEBUG,
                        format='%(asctime)s %(levelname)-8s %(message)s',
                        datefmt='%a, %d %b %Y %H:%M:%S',
                        filename=LOG_FILENAME,
                        filemode='w')
    # the following is from http://docs.python.org/library/logging.html#logging-to-multiple-destinations
    # define a Handler which writes INFO messages or higher to the sys.stderr
    console = logging.StreamHandler()
    console.setLevel(logging.INFO)
    # set a format which is simpler for console use
    formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
    # tell the handler to use this format
    console.setFormatter(formatter)
    # add the handler to the root logger
    logging.getLogger('').addHandler(console)

def logPrint( message ):
    logging.info( message )
    
def doesPathExist( filepath ):
    return os.path.exists( filepath )

def getFileSizeInKB( filepath ):
    assert( doesPathExist( filepath ) )
    return os.path.getsize( filepath ) / 1000.0

def getDOW2UserDataFolder():
    userProfileDir = os.environ['USERPROFILE']
    dow2UserDataFolder = userProfileDir + MYDOCUMENTS_DOW2_USERDATA_PATH
  
    dow2UserDataFolderExists = doesPathExist( dow2UserDataFolder )
  
    logPrint( "The default DOW2 userdata folder: " + dow2UserDataFolder + " exists: " + str(dow2UserDataFolderExists) )
    
    if( dow2UserDataFolderExists is True ):
        return dow2UserDataFolder
    
    # scan for location of folder in some clever way
    
    return ''

def getGFWLUserDataFolder():
    userProfileDir = os.environ['USERPROFILE']
    win7Fullpath = userProfileDir + APPDATA_GFWL_USERDATA_PATH_Win7
    xpFullpath = userProfileDir + APPDATA_GFWL_USERDATA_PATH_XP
  
    pathExists = doesPathExist( win7Fullpath )
    logPrint( "The default GFWL userdata folder: " + win7Fullpath + " exists: " + str(doesPathExist) )
    
    if pathExists:
        return win7Fullpath
    
    pathExists = doesPathExist( xpFullpath )
    logPrint( "The default GFWL userdata folder: " + xpFullpath + " exists: " + str(doesPathExist) )
    
    if pathExists:
        return xpFullpath
    # scan for location of folder in some clever way
    
    return ''

def backupSavegames():
    # backup savegames
    ## find my documents folder
    ## quick search for dow2 folder (Documents/My Game/Dawn of War 2/ usually)
    ## if not found, deep search for folder (log)
    ## if found
    ### log all found files in Saved Games folder (and sizes)
    ### zip contents of Saved Games folder into local zip
    ### log success and output filename (and size)
    ## if not found, log places looked
    dataFolder = getDOW2UserDataFolder()
    
    if dataFolder == '':
        #error
        logPrint( "Unable to find the DOW2 Saved Games folder, so cannot backup savegames" )
        return
    
    if doesPathExist( DEFAULT_BACKUP_ZIP_FILENAME ):
        # if we don't want to overwrite, log error, already exists
        logPrint( DEFAULT_BACKUP_ZIP_FILENAME + " already exists, please choose to overwrite or remove the file" )
        return
    
    outputZip = zipfile.ZipFile( DEFAULT_BACKUP_ZIP_FILENAME, 'w' )

    for dirpath, dirnames, filenames in os.walk( dataFolder ):
        for saveGame in filenames:
            fullFilepath = os.path.join( dirpath, saveGame )
            logPrint( "Backing up: " + fullFilepath + " ... filesize: " + str( getFileSizeInKB( fullFilepath ) ) + "KB" )
            outputZip.write( fullFilepath, os.path.basename( fullFilepath ), zipfile.ZIP_DEFLATED )
            # put into local zip
    
    outputZip.close()
    logPrint( "Successfully zipped savegame files" )  

def restoreSavegames( zipFilepath ):
    # restore savegames
    ## take zip filepath as input
    ## log if not found or openable
    ## use same routines that backup does to find existing dow2 data folder
    ## report if Save Games exists already or not
    ## restore contents of zip into folder
    ## report if files already exist, do not overwrite
    ## log success and written files (and their sizes)

    logPrint( "Attempting to restore savegames from: " + zipFilepath )
    
    if not doesPathExist( zipFilepath ):
        logPrint( "File not found: " + zipFilepath + " unable to restore savegames" )
        return

    dataFolder = getDOW2UserDataFolder()
    
    if dataFolder == '':
        #error
        logPrint( "Unable to find the DOW2 Saved Games folder, so cannot restore savegames" )
        return
        
    inputZipfile = zipfile.ZipFile( zipFilepath, 'r' )
    
    for zippedFile in inputZipfile.namelist():
        if doesPathExist( os.path.join( dataFolder, zippedFile ) ):
            logPrint( "Destination file: " + zippedFile + " already exists in " + zipFilepath + ", skipping extraction of this file" )
            continue
        
        logPrint( "Extracting: " + zippedFile + " from " + zipFilepath )
        inputZipfile.extract( zippedFile, dataFolder )
        
    inputZipfile.close()
    
    logPrint( "Completed restoration of save games from: " + zipFilepath )

def backupGFWLProfiles():
    # backup GFWL profiles
    ## scan for GFWL profiles (Application Settings/Microsoft/XLive/Content/ usually)
    ## attempt to identify profiles (gamertag photos are easy, figure out how name is stored)
    ## prompt for which gamertags to backup data for (log all)
    ## if there is at least one chosen, zip its root folder into a zip file in the local dir
    ## write simple text file with folder -> gamertag mapping for easier restore
    ## log size of zip file and filename

    pass

def restoreGFWLProfles( zipFilePath ):
    # restore GFWL profiles
    ## take zip filepath as input
    ## log if not found or openable
    ## scan for valid GFWL folder structure
    ## prompt if not found, * find out if this is possible with a fresh GFWL install?*
    ## display choice based on simple text file in zip
    ## if there is at least one chosen, zip its root folder into the appropriate place
    pass

def main():
    loggingSetup()

    if len( sys.argv ) <= 1:
        logPrint( "Please run with -savebackup or -saverestore <FilepathToRestoreArchive>" )
        return

    if sys.argv[1] == "-savebackup":     
        backupSavegames()
    elif sys.argv[1] == "-saverestore":
        restoreSavegames( sys.argv[2] )

    #restoreSavegames( "DOW2SaveGamesBackup.zip" )

if __name__ == "__main__":
    sys.exit( main() )

